#ifndef SERVER_CLIENT_THREAD_H_
#define SERVER_CLIENT_THREAD_H_
#include "../SocketsAndThreads/socket.h"
#include "../SocketsAndThreads/thread.h"
#include "../SocketsAndThreads/mutex.h"
#include "../Utils/directoryHandler.h"
#include "../Utils/Decoder.h"
#include "../Utils/index.h"
#include <ctime>
#include <vector>
#include <map>
#include <log4cpp/Category.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/SimpleLayout.hh>

//Variable global utilizada para loggear a un archivo
extern log4cpp::Category& category;

class ClientThread: public Thread {
private:

	//Path donde se guardan los archivos
	string files_path;
	//Path de la carpeta de almacenamiento del usuario
	string user_path;
	//Mutex para proteger datos compartidos entre threads
	Mutex* all_clients_mutex;
	//Socket para la comunicacion
	Socket* s;
	//Los indices de los usuarios conectados hasta ahora
	map<string, Index*>* used_indexes;
	//Metodo para esperar por login
	string WaitForLogin(unsigned int max_tries);
	//Procesa los mensajes
	void process(Message*, int);
	//Se encargan de realizar las tareas necesarias para cada mensaje
	void WaitForMsgs();
	void ProcessGetFile(GetFile* msg);
	void ProcessGetFilesList();
	void ProcessDeleteFile(Delete* df);
	void ProcessPutFile(PutFile* pf);
	void ProcessUnregister();
	//Intenta Reconstruir el indice de archivos, si este esta vacio
	void RecoverIndex();
	//Indice de los archivos del usuario loggeado
	Index* files_index;
	//Mutex para clientes loggeados al mismo usuario
	Mutex* same_user_mutex;
	//Busca si ya esta levantado el indice del usuario requerido
	Index* FindUserIndex(string* user_name);
	//Vector donde estan los threads de todos los clientes conectados
	vector<ClientThread*>* clients_threads;
	//Notifica a todos los usuarios de una cuenta sobre cambios en cierto archivo
	void NotifyUsers(char notify_type, string* file_name);
	//Puntero a variable con bytes almacenados hasta ahora en total
	unsigned int* stored_bytes;
	//Verifica si el loggeo fue exitoso o no
	bool LoginValidation(string* user, string *pass);
public:
	//True si el usuario se loggeo
	bool logged;
	//Time stamp que guarda la ultima interaccion con el usuario
	unsigned int last_interaction;
	//Guarda la ip del cliente conectado
	string ip;
	//Usuario de la cuenta (si se logro loggear)
	string user_name;
	//Password de la cuenta (si se logro loggear)
	string password;
	ClientThread(Socket* s, vector<ClientThread*>* clients_threads,
			Mutex* all_clients_mutex, map<string, Index*>* used_indexes,
			string* files_path, unsigned int* stored_bytes);
	~ClientThread();
	//Metodo con la funcionalidad del thread
	void run();
	//Pone el estado del thread en false y hace shutdown al socket
	void stop();

};

#endif /* SERVER_CLIENT_THREAD_H_ */
